#ifndef _XL_LIB_UPLOADER_H
#define _XL_LIB_UPLOADER_H

#include <tchar.h>
#include <string>
#include <sstream>
#include <vector>

// #ifndef wstring
// typedef std::basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring;
// #endif

#define CURL_STATICLIB
#define PCRE_STATIC
#include "curl/curl.h"
#include "htmlcxx/html/ParserDom.h"
#include "pcre/pcre.h"


#ifdef WIN32
#ifdef NDEBUG
#	pragma comment (lib, "../3rd/libs/release/htmlcxx.lib")
#else
#	pragma comment (lib, "../3rd/libs/debug/htmlcxx.lib")
#endif
#	pragma comment (lib, "../3rd/libs/release/libcurl.lib")
#	pragma comment (lib, "../3rd/libs/release/pcre.lib")
#	pragma comment (lib, "../3rd/libs/release/ssleay32.lib")
#	pragma comment (lib, "../3rd/libs/release/libeay32.lib")
#	pragma comment (lib, "../3rd/libs/release/zlib.lib")
#	pragma comment (lib, "ws2_32.lib")
#	pragma comment (lib, "Wldap32.lib")
#endif

//////////////////////////////////////////////////////////////////////////
// defines
#ifndef COUNT_OF
#define COUNT_OF(x)                     (sizeof(x)/sizeof((x)[0]))
#endif


//////////////////////////////////////////////////////////////////////////
// typedef
#ifdef UNICODE
typedef std::wstring                    tstring;
typedef std::wstringstream              tstringstream;
#else
typedef std::string                     tstring;
typedef std::stringstream               tstringstream;
#endif



//////////////////////////////////////////////////////////////////////////
// html
typedef htmlcxx::HTML::Node             HtmlNode;
typedef tree<HtmlNode>                  HtmlDom;
typedef HtmlDom::iterator               HtmlNodeIter;
typedef HtmlDom::sibling_iterator       HtmlNodeSiblingIter;
typedef std::vector<HtmlNodeIter>       HtmlNodeIterArray;

HtmlDom html_load (const std::string &html);
HtmlNodeIter html_get_node_by_tag (HtmlDom &dom, const std::string &tag, int index = 0);
HtmlNodeIterArray html_get_nodes_by_tag (const HtmlDom &dom, const std::string &tag);
HtmlNodeIter html_get_node_by_id (HtmlDom &dom, const std::string &id);
HtmlNodeIterArray html_get_children (HtmlDom &dom, HtmlNodeIter &parent, const std::string &tag = "");
HtmlNodeIterArray html_get_children_by_id (HtmlDom &dom, const std::string &id, const std::string &tag = "");


//////////////////////////////////////////////////////////////////////////
// http
/************************************************************************
 typedef int (*curl_progress_callback) (
                                        void *clientp,
                                        double dltotal,
                                        double dlnow,
                                        double ultotal,
                                        double ulnow
                                       );
 ************************************************************************/
typedef curl_progress_callback         HttpProgressCallback;
typedef CURLcode                       HttpCode;

void http_set_proxy(const std::string &proxy);
void http_clear_proxy();

HttpCode http_get (
                   std::string &output,
                   const char *url,
                   std::string &cookie, // in/out
                   HttpProgressCallback callback = NULL,
                   void *callback_param = NULL,
                   std::string referer = ""
                  );

/**
 * @url action of the form
 * @file_pathname the path name of the file
 * @note this function should not be used outside the lib itself
 */
HttpCode http_post (
                    std::string &output,
                    const std::string &url,
                    HtmlNodeIterArray inputs,
                    const TCHAR *file_pathname,
                    std::string &cookie, // in/out
                    HttpProgressCallback callback = NULL,
                    void *callback_param = NULL,
                    const std::string referer = ""
                   );
/**
 * @url the url to get the form
 * @file_pathname the path name of the file
 */
HttpCode http_upload (
                      std::string &output,
                      const std::string &url,
                      const TCHAR *file_pathname,
                      std::string &cookie, // in/out
                      HttpProgressCallback callback = NULL,
                      void *callback_param = NULL
                     );


//////////////////////////////////////////////////////////////////////////
// utils
size_t file_put_contents(const TCHAR *file, const std::string &contents);
size_t file_put_contentsA(const char *file, const std::string &contents);

bool file_get_contents(const TCHAR *file, std::string &contents);
bool file_get_contentsA(const char *file, std::string &contents);

std::string util_w2utf8 (const std::wstring &ws);
std::wstring util_mbs2ws (const std::string &mbs);
tstring util_mbs2tcs(const std::string &mbs);

// try to make it lik php::explode()
std::vector<std::string> util_explode(const std::string &delimiter, const std::string &str, int max_parts = -1);

std::string util_get_mime_by_name (const tstring &name);

// create url from base & action, used for get full action url of <form action="xxx">
// form_url is the form url
std::string util_get_form_action_url (const std::string &form_url, const std::string &action);
bool util_get_form_action_url_test();

// clipboard
std::string util_clipboard_get_html_format(const std::string &fragment, const std::string &src = "");


#ifdef __cplusplus
// tstring
/**
 * used for case insensitive compare
 */
template<class T>
struct func_tstring_iless : public std::binary_function<T, T, bool> {
	bool operator()(const T &lhs, const T &rhs) const;
};
template<>
struct func_tstring_iless<tstring> : public std::binary_function<tstring, tstring, bool> {
	bool operator()(const tstring &lhs, const tstring &rhs) const {
		if (_tcsicmp(lhs.c_str(), rhs.c_str()) < 0) {
			return true;
		} else {
			return false;
		}
	}
};
#endif




//////////////////////////////////////////////////////////////////////////
// ISite interface
class ISite
{
public:
	const static HttpCode PATTERN_NOT_FOUND = CURLE_TFTP_NOTFOUND;

	virtual ~ISite() {}

	/**
	 * return the site name
	 */
	virtual TCHAR* getSiteName () = 0;

	/**
	 * update a file (fileName), and save the image url into imageurl_or_response.
	 * @return
	 *  - CURLE_OK if all is OK
	 *  - ISite::PATTERN_NOT_FOUND if can't find image url in the response, and 
	 *    imageurl_or_response will be the response text from the server.
	 */
	virtual HttpCode uploadFile (
                                     std::string &imageurl_or_response,
                                     const TCHAR *fileName,
                                     HttpProgressCallback progressCb = NULL,
				     void *progressParam = NULL
                                    ) = 0;
};

//////////////////////////////////////////////////////////////////////////
// Site Manager as a singleton.
class CSiteManager
{
private:
	CSiteManager();
	~CSiteManager();

	// static CSiteManager *m_instance;
	typedef std::vector<ISite *> Container;
	Container m_sites;

public:
	static CSiteManager* getInstance();
	
	bool addSite(ISite *);
	bool removeSite(ISite *);

	size_t getSiteCount() const;
	ISite* getSiteByIndex(size_t index);

};

// debug
ISite* debugGetSite();
// #define DEBUG_SIZE_IMGPLACE
// #define DEBUG_SIZE_TINYPIC
#define DEBUG_SIZE_IMAGEHOST_ORG



#endif
